#pragma once

#include "../common/Dispatcher.hpp"
#include "../client/RpcClient.hpp"
#include "RpcRegistry.hpp"
#include "RpcRouter.hpp"
#include "RpcTopic.hpp"

namespace rpc
{
    namespace server
    {
        // 服务注册发现模块与网络通信部分
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(uint16_t port)
                : _pd_manager(std::make_shared<PDManager>())
                , _dispatcher(std::make_shared<Dispatcher>())
            {
                auto req_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(), 
                    std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<ServiceRequest>(MSG_TYPE::REQ_SERVICE, req_cb);

                _server = ServerFactory::create(port);
                auto msg_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(),
                    std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(msg_cb);

                auto close_cb = std::bind(&RegistryServer::onConnShutdown, this,
                    std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }

            void start()
            {
                _server->start();
            }

        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _pd_manager->onConnShutDown(conn);
            }
        private:
            PDManager::ptr _pd_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
        
        // rpc功能模块和网络通信部分结合
        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            // 1. rpc服务提供端访问地址
            // 2. 服务注册中心地址
            RpcServer(const Address &access_address, bool enable = false, const Address &registry_address = Address())
                : _access_address(access_address)
                , _enable_registryclient(enable)
                , _rpc_router(std::make_shared<RpcRouter>())
                , _dispatcher(std::make_shared<Dispatcher>())
            {
                if (enable == true)
                {
                    _registry_client = std::make_shared<client::RegistryClient>(registry_address.first, 
                        registry_address.second);
                }

                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _rpc_router.get(), 
                    std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<RpcRequest>(MSG_TYPE::REQ_RPC, rpc_cb);

                _server = ServerFactory::create(_access_address.second);
                auto msg_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), 
                    std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(msg_cb);
            }

            void registryService(const ServiceDescribe::ptr &service)
            {
                if (_enable_registryclient)
                {
                    _registry_client->registryService(_access_address, service->method());
                }
                _rpc_router->registerService(service);
            }

            void start()
            {
                _server->start();
            }
        private:
            Address _access_address; // rpc服务提供端地址
            bool _enable_registryclient;
            client::RegistryClient::ptr _registry_client;
            RpcRouter::ptr _rpc_router;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(const uint16_t &port)
                : _topic_manager(std::make_shared<TopicManager>())
                , _dispatcher(std::make_shared<Dispatcher>())
            {
                auto topic_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(),
                    std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<TopicRequest>(MSG_TYPE::REQ_TOPIC, topic_cb);

                _server = ServerFactory::create(port);
                auto msg_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(),
                    std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(msg_cb);

                auto close_cb = std::bind(&TopicServer::onConnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }

            void start()
            {
                _server->start();
            }
        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _topic_manager->onConnShutdown(conn);
            }

        private:
            TopicManager::ptr _topic_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
    }
}